﻿using Mockery.Core;
using NUnit.Framework;
using Rhino.Mocks;

namespace Mockery.UnitTest
{
    [TestFixture]
    public class ActiveMockeryStateTests
    {
        [Test]
        public void ActiveMockeryState_ValidateDefaultState()
        {
            var mocks = new MockRepository();
            var repositoryStateHandler = mocks.Stub<IRepositoryStateHandler>();

            Assert.That(new ActiveMockeryState(repositoryStateHandler).State, Is.EqualTo(MockeryState.Setup));
        }


        [Test]
        public void ActiveMockeryState_SetState()
        {
            const MockeryState testState = MockeryState.Arrange;

            var mocks = new MockRepository();
            var repositoryStateHandler = mocks.StrictMock<IRepositoryStateHandler>();

            mocks.Record();

            Expect.Call(() => repositoryStateHandler.SetState(testState));

            mocks.ReplayAll();
    
            var activeMockeryState = new ActiveMockeryState(repositoryStateHandler);

            activeMockeryState.SetState(testState);

            mocks.VerifyAll();

            Assert.That(activeMockeryState.State, Is.EqualTo(testState));
        }

        [Test]
        public void ActiveMockeryState_SetState_OutOfOrderTest()
        {
            var testActState = MockeryState.Act;

            var mocks = new MockRepository();
            var repositoryStateHandler = mocks.StrictMock<IRepositoryStateHandler>();

            mocks.Record();

            Expect.Call(() => repositoryStateHandler.SetState(testActState));

            mocks.ReplayAll();
            
            var activeMockeryState = new ActiveMockeryState(repositoryStateHandler);

            activeMockeryState.SetState(testActState);

            Assert.Throws<MockeryOrderException>(() => activeMockeryState.SetState(MockeryState.Arrange));

            mocks.VerifyAll();
        }

        [Test]
        public void ActiveMockeryState_SetState_ValidateSingleRepositoryCallOnMultipleStateCallTests()
        {
            var testActState = MockeryState.Act;

            var mocks = new MockRepository();
            var repositoryStateHandler = mocks.StrictMock<IRepositoryStateHandler>();

            mocks.Record();

            Expect.Call(() => repositoryStateHandler.SetState(testActState)).Repeat.Once();

            mocks.ReplayAll();

            var activeMockeryState = new ActiveMockeryState(repositoryStateHandler);

            activeMockeryState.SetState(testActState);

            activeMockeryState.SetState(testActState);

            mocks.VerifyAll();
        }

        [Test]
        public void ActiveMockeryState_AssertMockeryStateOrder()
        {
            Assert.That(MockeryState.Setup < MockeryState.Arrange);
            Assert.That(MockeryState.Arrange < MockeryState.Act);
            Assert.That(MockeryState.Act < MockeryState.Assert);
        }
    }
}
